package com.gack.helper.aspect;

import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.gack.business.model.UrlAndPermission;
import com.gack.business.model.UserEnterprisePermissionGroup;
import com.gack.business.repository.PermissionRepository;
import com.gack.business.repository.UserEnterprisePermissionGroupRepository;
import com.gack.business.service.PermissionServiceInterface;
import com.gack.helper.common.AjaxJson;
import com.gack.helper.common.config.UrlAndPermissionConfig;
import com.gack.helper.common.util.MapAsReturn;

import io.jsonwebtoken.lang.Collections;

/**
 * 
 * @author ws
 * 2018-8-3
 */
@Aspect
@Component
public class PermissionAspect {

	private static final Logger logger = LoggerFactory.getLogger(PermissionAspect.class);

	@Autowired
	private UrlAndPermissionConfig urlAndPermissionConfig;
	@Autowired
	private PermissionServiceInterface permissionService;
	@Autowired
	private UserEnterprisePermissionGroupRepository userEnterprisePermissionGroupRepository;
	@Autowired
	private PermissionRepository permissionRepository;
	
	@Order(1)
	@Around("execution(* com.gack.business.controller.*.*(..))")
	public Object handleControllerMethod(ProceedingJoinPoint pjp) throws Throwable{
		AjaxJson ajaxJson = new AjaxJson();
		
		//获取需要拦截的url及其所需权限	若无url需拦截,则放过请求url
        List<UrlAndPermission> uapList = urlAndPermissionConfig.getUrlAndPermission();
        if(uapList == null || uapList.size() == 0){
        	return pjp.proceed();
        }
        
        //获取uri、HTTP请求方法
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();
        String uri = request.getRequestURI();//获取uri
        String method = request.getMethod();//获取HTTP请求方法

        //获取执行请求url所需要的权限       permission：操作者所需权限-被操作者不能具备的权限(若无-则表示被操作者可以具备任意权限或不具备权限)。
        String needPermission = null;
        for(UrlAndPermission t : uapList){
        	if(uri.matches(t.getUrl()) && method.equalsIgnoreCase(t.getMethod())){
        		needPermission = t.getPermission();
        		break;
        	}
        }
        
        //若needPermission为空则放过请求url
        if(StringUtils.isBlank(needPermission)){
        	return pjp.proceed();
        }

        //若needPermission不为空,则判断所需权限条件是否符合
        //获取操作者id、公司id、被操作者id
        String operatorId = request.getParameter("permissionUserId");
        String enterpriseId = request.getParameter("permissionEnterpriseId");
        String userId = request.getParameter("userId");//可为空
        
        //若操作者id或公司id为空,则权限判断失败,返回错误信息
        if(StringUtils.isBlank(operatorId) || StringUtils.isBlank(enterpriseId)){
        	logger.error("请求路径:" + request.getRequestURI() + "  "
					+ pjp.getSignature().getDeclaringTypeName() + "判断权限失败");
        	return  ajaxJson.setSuccess(true).setStatus(200).setData(MapAsReturn.setStatusError("权限判断失败。请求路径:" + request.getRequestURI()));
        }
        
        //查询操作者所具有的权限
        UserEnterprisePermissionGroup operatorUepg = userEnterprisePermissionGroupRepository.findByUserIdAndEnterpriseId(operatorId, enterpriseId);
        if(null == operatorUepg){
        	return ajaxJson.setSuccess(true).setStatus(200).setData(MapAsReturn.setStatusError("您不具备权限"));
        }
        List<String> operatorPermissionDescList = operatorUepg.getOpenDescription();
        if(operatorPermissionDescList.contains("SUPER_PERMISSION")){
        	operatorPermissionDescList = permissionRepository.findAllDescription();
		}
        
        //判断操作者是否具有特定权限
        String[] needPermissionArray = needPermission.split(";");
        boolean flag = false;
        for(String needPermissionElement : needPermissionArray){
        	String[] perm = needPermissionElement.split("-");
        	if(perm.length == 1){//只需检查操作者权限
        		if(matchPermission(operatorPermissionDescList, perm[0])){
        			flag = true;
        			break;
        		}
        	}else if(perm.length == 2){//检查操作者和被操作者权限
        		if(userId != null){
        			UserEnterprisePermissionGroup userUepg = userEnterprisePermissionGroupRepository.findByUserIdAndEnterpriseId(userId, enterpriseId);
        			List<String> userPermissionDescList = null;
        			if(null != userUepg){
        				userPermissionDescList = userUepg.getOpenDescription();
        				if(userPermissionDescList.contains("SUPER_PERMISSION")){
        					userPermissionDescList = permissionRepository.findAllDescription();
        				}
        			}
	        		if(matchPermission(operatorPermissionDescList, perm[0], userPermissionDescList, perm[1])){
	        			flag = true;
	        			break;
	        		}
        		}
        	}
        }
        
        if(!flag){
        	return ajaxJson.setSuccess(true).setStatus(200).setData(MapAsReturn.setStatusError("您不具备相应操作权限"));
        }
        
		return pjp.proceed();
	}
	
	/**
	 * 检查操作者是否具有所需权限
	 * @param operatorPermissionDescList 操作者具有的权限的英文描述集合
	 * @param needOperatorPermissionDesc 需要操作者具有的权限的英文描述
	 * @return 操作者具有该权限--true    操作者不具有该权限--false
	 */
	private boolean matchPermission(List<String> operatorPermissionDescList, String needOperatorPermissionDesc){
		return operatorPermissionDescList.contains(needOperatorPermissionDesc);
	}
	
	/**
	 * 检查操作者是否具有所需权限,并且被操作者不具有某权限
	 * @param operatorPermissionDescList 操作者具有的权限的英文描述集合
	 * @param needOperatorPermissionDesc 需要操作者具有的权限的英文描述
	 * @param userPermissionDescList 被操作者具有的权限的英文描述集合
	 * @param needNoUserPermissionDesc 被操作者不能具有的权限的英文描述
	 * @return 操作者和被操作者的权限满足条件--true   操作者和被操作者的权限不满足条件--false
	 */
	private boolean matchPermission(List<String> operatorPermissionDescList, String needOperatorPermissionDesc, List<String> userPermissionDescList, String needNoUserPermissionDesc){
		return operatorPermissionDescList.contains(needOperatorPermissionDesc) && (Collections.isEmpty(userPermissionDescList) || !userPermissionDescList.contains(needNoUserPermissionDesc));
	}
}
